@*****************************************************************
@ File:start.S
@ Author:ficenow
@*****************************************************************

.text
.global _start                          @定义_start标号为全局属性
_start:                                 @入口地址

@异常向量表
    b reset
	ldr	pc, _undefined_instruction      @上电就运行的程序	
	ldr	pc, _software_interrupt		    @不用ldr pc, =xxxxxxxx是因为这里有可能还是在nor或stepping stone，不能进行绝对跳转
	ldr	pc, _prefetch_abort			
	ldr	pc, _data_abort				
	ldr	pc, _not_used				    @由ARM的数据手册可知在预取数据异常和IRQ异常之间多空出了一个存储单元0x00000014,
                                        @所以在这个地址处不做任何实质性的事情
	ldr	pc, _irq					
	ldr	pc, _fiq

@存放实际异常入口地址开辟的存储单元
_undefined_instruction: .word undefined_instruction
_software_interrupt: .word software_interrupt
_prefetch_abort: .word prefetch_abort
_data_abort: .word data_abort
_not_used: .word not_used
_irq: .word irq
_fiq: .word fiq
_reset: .word reset

@实际的异常处理函数
undefined_instruction:
    nop

software_interrupt:
    nop

prefetch_abort:
    nop

data_abort:
    nop

not_used:
    nop

irq:
    sub lr, lr, #4 /* 保存环境 */
    stmfd sp!, {r0-r12, lr}
    bl handle_int
    ldmfd sp!, {r0-r12, pc}^    /* 恢复现场，表示把spsr恢复到cpsr */

fiq:
    nop

reset:
    bl set_svc
    bl disable_watchdog
    bl disable_interrupt
    bl disable_mmu

    bl clock_init
    bl init_sdram
    bl init_stack
    bl clean_bss

    bl nand_init
    bl copy_to_ram
    ldr pc, =ice_boot_main
    @bl light_led

set_svc:
    mrs r0, cpsr
    bic r0, #0x1f
    orr r0, #0xd3    @屏蔽了IRO和FIQ
    msr cpsr, r0
    mov pc, lr

#define pWTCON 0X53000000
disable_watchdog:
    ldr r0, =pWTCON
    mov r1, #0x0
    str r1, [r0]
    mov pc, lr

#define pINTMASK 0x4a000008
disable_interrupt:
    mvn r1, #0x0
    ldr r0, =pINTMASK
    str r1, [r0]
    mov pc, lr

disable_mmu:
    mcr p15,0,r0,c7,c7,0    @使ICache和DCache失效
    mrc p15,0,r0,c1,c0,0    @读control register
    bic r0, r0, #0x00000007
    mcr p15,0,r0,c1,c0,0
    mov pc, lr

#define CLKDIVN 0X4C000014
#define MPLLCON 0X4C000004
#define MPLL_405MHZ ((127<<12) | (2<<4) | (1<<0))
clock_init:
    ldr r0, =CLKDIVN
    mov r1, #0x05           @分频系数FCLK:HCLK:PCK为1:4:8
    str r1, [r0]

    mrc p15,0,r0,c1,c0,0
    orr r0,r0,#0xc0000000    @设置异步模式
    mcr p15,0,r0,c1,c0,0
    
    ldr r0, =MPLLCON
    ldr r1, =MPLL_405MHZ
    str r1, [r0] 

    mov pc, lr

#define mem_control 0x48000000
init_sdram:
    ldr r0, =mem_control
    add r3, r0, #4*13
    adrl r1, mem_data

set_mem:
    ldr r2, [r1], #4
    str r2, [r0], #4
    cmp r0, r3
    bne set_mem 

    mov pc, lr

mem_data:
    .long 0x22000000
    .long 0x00000700
    .long 0x00000700
    .long 0x00000700
    .long 0x00000700
    .long 0x00000700
    .long 0x00000700
    .long 0x00018001
    .long 0x00018001
    .long 0x008C04F5
    .long 0x000000B1
    .long 0x00000030
    .long 0x00000030

copy_to_ram:
    mov r0, #0
    ldr r1, =_start
    ldr r2, =bss_end
    sub r2, r2, r1

    mov ip, lr
    bl nand_to_ram
    mov lr, ip

    mov pc, lr

init_stack:
    msr cpsr_c, #0xD2
    ldr sp, =0x33000000     //初始化R13_irq
    msr cpsr_c, #0xD3
    ldr sp, =0x34000000     //初始化R13_svc(0x30000000+64M)
    mov pc, lr

clean_bss:
    ldr r0, =bss_start
    ldr r1, =bss_end
    cmp r0, r1
    moveq pc, lr

clean_loop:
    mov r2, #0
    str r2, [r0], #4
    cmp r0, r1
    bne clean_loop
    mov pc, lr

#define GPBCON 0x56000010
#define GPBDAT 0x56000014
light_led:
   ldr r0, =GPBCON 
   ldr r1, = 0x15400    @设置GPB5-GPB8为OUTPUT
   str r1, [r0] 
   
   ldr r0, =GPBDAT 
   ldr r1, = 0x75F  @点亮LED1和LED3
   str r1, [r0]

   mov pc, lr
